كيفية الدمج مع مفاتيح وسائط الأجهزة وتخصيص إشعارات الوسائط وغير ذلك
تم طرح واجهة برمجة التطبيقات Media Session API لإعلام المستخدمين بالمحتوى الذي يتم تشغيله حاليًا في المتصفّح والتحكّم فيه بدون الرجوع إلى الصفحة التي تم تشغيله منها. ويسمح هذا المعيار لمطوّري الويب بتخصيص هذه التجربة من خلال البيانات الوصفية في إشعارات الوسائط المخصّصة وأحداث الوسائط، مثل التشغيل والإيقاف المؤقت والتقديم والترجيع وتغيير المقطع الصوتي، وأحداث مؤتمرات الفيديو، مثل كتم/إلغاء كتم الميكروفون وتفعيل/إيقاف الكاميرا وإغلاق المكالمة. تتوفّر هذه التخصيصات في عدة سياقات، بما في ذلك مراكز الوسائط على أجهزة الكمبيوتر المكتبي وإشعارات الوسائط على الأجهزة الجوّالة وحتى على الأجهزة القابلة للارتداء. سأوضّح هذه التخصيصات في هذه المقالة.

لمحة عن Media Session API
توفّر واجهة برمجة التطبيقات Media session API العديد من المزايا والإمكانات:
- مفاتيح الوسائط في الأجهزة متوافقة.
- يتم تخصيص إشعارات الوسائط على الأجهزة الجوّالة وأجهزة الكمبيوتر المكتبي والأجهزة القابلة للارتداء المقترنة.
- يتوفّر مركز الوسائط على أجهزة الكمبيوتر المكتبي.
- تتوفّر عناصر التحكّم في الوسائط على شاشة القفل على أجهزة ChromeOS والأجهزة الجوّالة.
- تتوفّر عناصر التحكّم في نافذة "صورة في صورة" لتشغيل الصوت، اجتماعات الفيديو، وعرض الشرائح.
- تتوفر ميزة دمج "مساعد Google" على الأجهزة الجوّالة.
سنوضّح بعض هذه النقاط من خلال بعض الأمثلة.
المثال 1: إذا ضغط المستخدمون على مفتاح الوسائط "الأغنية التالية" على لوحة المفاتيح، يمكن لمطوّري الويب معالجة هذا الإجراء الذي يتّخذه المستخدم سواء كان المتصفّح في المقدّمة أو الخلفية.
المثال 2: إذا كان المستخدمون يستمعون إلى بودكاست على الويب بينما كانت شاشة الجهاز مقفلة، سيظل بإمكانهم النقر على رمز "التقديم/الترجيع" من عناصر التحكّم في الوسائط على شاشة القفل ليتمكّن مطوّرو الويب من ترجيع وقت التشغيل بضع ثواني.
المثال 3: إذا كان لدى المستخدمين علامات تبويب تشغّل الصوت، يمكنهم بسهولة إيقاف التشغيل من مركز الوسائط على الكمبيوتر المكتبي حتى يتمكن مطوّرو الويب من محو حالتهم.
المثال 4: إذا كان المستخدمون يشاركون في مكالمة فيديو، يمكنهم الضغط على عنصر التحكّم "تبديل الميكروفون" في نافذة "صورة في صورة" لإيقاف الموقع الإلكتروني عن تلقّي بيانات الميكروفون.
ويتم تنفيذ كل ذلك من خلال واجهتَين مختلفتَين: واجهة MediaSession
وواجهة MediaMetadata
. يتيح الخيار الأول للمستخدمين التحكّم في المحتوى الذي يتم تشغيله. أما الطريقة الثانية، فهي كيفية إخبار MediaSession
بما يجب التحكّم فيه.
على سبيل المثال، توضِّح الصورة أدناه كيفية ارتباط هذه الواجهات بعناصر تحكّم معيّنة في الوسائط، وفي هذه الحالة إشعار وسائط على جهاز جوّال.

إطلاع المستخدمين على المحتوى الذي يتم تشغيله
عندما يشغّل موقع إلكتروني محتوى صوتيًا أو فيديو، يتلقّى المستخدمون تلقائيًا إعلامات بشأن الوسائط في مربّع الإشعارات على الأجهزة الجوّالة أو في مركز الوسائط على أجهزة الكمبيوتر المكتبي. يبذل المتصفّح قصارى جهده لعرض المعلومات المناسبة باستخدام عنوان الوثيقة وأكبر صورة رمز يمكنه العثور عليها. باستخدام واجهة برمجة التطبيقات Media Session API، من الممكن تخصيص إشعار الوسائط باستخدام بعض البيانات الوصفية الغنية عن الوسائط ، مثل العنوان واسم الفنان واسم الألبوم والعمل الفني، كما هو موضّح أدناه.
لا يطلب Chrome التركيز الكامل على الصوت لعرض إشعارات الوسائط إلا عندما تكون مدة الوسائط 5 ثوانٍ على الأقل. يضمن ذلك عدم عرض الإشعارات عند سماع أصوات عرضية، مثل أصوات التنبيه.
// After media (video or audio) starts playing
await document.querySelector("video").play();
if ("mediaSession" in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: 'Never Gonna Give You Up',
artist: 'Rick Astley',
album: 'Whenever You Need Somebody',
artwork: [
{ src: 'https://via.placeholder.com/96', sizes: '96x96', type: 'image/png' },
{ src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
{ src: 'https://via.placeholder.com/192', sizes: '192x192', type: 'image/png' },
{ src: 'https://via.placeholder.com/256', sizes: '256x256', type: 'image/png' },
{ src: 'https://via.placeholder.com/384', sizes: '384x384', type: 'image/png' },
{ src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
]
});
// TODO: Update playback state.
}
عند انتهاء التشغيل، ليس عليك "إلغاء" جلسة الوسائط لأنّه
سيختفي الإشعار تلقائيًا. يُرجى العِلم أنّه سيتم استخدام navigator.mediaSession.metadata
عند بدء التشغيل التالي. لهذا السبب، من المهم تعديله عند تغيُّر مصدر تشغيل الوسائط لضمان عرض المعلومات ذات الصلة في إشعار الوسائط.
في ما يلي بعض الملاحظات حول بيانات التعريف للوسائط.
- تتيح صفيفات الأعمال الفنية للإشعارات استخدام عناوين URL للكائنات الثنائية الكبيرة وعناوين URL للبيانات.
- إذا لم يتم تحديد عمل فني وكان هناك صورة رمز (يتم تحديدها باستخدام
<link rel=icon>
) بالحجم المطلوب، ستستخدم إشعارات الوسائط هذا الرمز. - الحجم المستهدَف لأعمال فنية الإشعارات في Chrome لنظام التشغيل Android هو
512x512
. بالنسبة إلى الأجهزة المنخفضة المستوى، تكون القيمة256x256
. - يتم استخدام سمة
title
لعنصر HTML للوسائط في تطبيق "المحتوى الذي يتم تشغيله حاليًا" على أجهزة macOS. - إذا كان مورد الوسائط مضمّنًا (على سبيل المثال في إطار iframe)، يجب ضبط معلومات Media Session API من السياق المضمّن. يُرجى الاطّلاع على المقتطف أدناه.
<iframe id="iframe">
<video>...</video>
</iframe>
<script>
iframe.contentWindow.navigator.mediaSession.metadata = new MediaMetadata({
title: 'Never Gonna Give You Up',
...
});
</script>
يمكنك أيضًا إضافة معلومات فردية عن الفصول، مثل عنوان القسم والطابع الزمني له وصورة لقطة شاشة إلى البيانات الوصفية للوسائط. يتيح ذلك للمستخدمين التنقّل في محتوى الوسائط.
navigator.mediaSession.metadata = new MediaMetadata({
// title, artist, album, artwork, ...
chapterInfo: [{
title: 'Chapter 1',
startTime: 0,
artwork: [
{ src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
{ src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
]
}, {
title: 'Chapter 2',
startTime: 42,
artwork: [
{ src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
{ src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
]
}]
});

السماح للمستخدمين بالتحكّم في المحتوى الذي يتم تشغيله
إجراء جلسة الوسائط هو إجراء (مثل "تشغيل" أو "إيقاف مؤقت") يمكن لأحد المواقع الإلكترونية
معالجته للمستخدمين عند تفاعلهم مع تشغيل الوسائط الحالي. الإجراءات مشابهة للأحداث وتعمل بالطريقة نفسها تقريبًا. مثل الأحداث، يتم تنفيذ الإجراءات
من خلال ضبط المعالِجات على عنصر مناسب، وهو مثيل
MediaSession
في هذه الحالة. يتم تنفيذ بعض الإجراءات عندما يضغط المستخدمون على buttons من سماعة رأس أو جهاز تحكّم عن بُعد آخر أو لوحة مفاتيح أو يتفاعلون مع إعلام إعلامات الوسائط.

بما أنّ بعض إجراءات جلسات الوسائط قد لا تكون متوافقة، ننصحك باستخدام try…catch
عند ضبطها.
const actionHandlers = [
['play', () => { /* ... */ }],
['pause', () => { /* ... */ }],
['previoustrack', () => { /* ... */ }],
['nexttrack', () => { /* ... */ }],
['stop', () => { /* ... */ }],
['seekbackward', (details) => { /* ... */ }],
['seekforward', (details) => { /* ... */ }],
['seekto', (details) => { /* ... */ }],
/* Video conferencing actions */
['togglemicrophone', () => { /* ... */ }],
['togglecamera', () => { /* ... */ }],
['hangup', () => { /* ... */ }],
/* Presenting slides actions */
['previousslide', () => { /* ... */ }],
['nextslide', () => { /* ... */ }],
];
for (const [action, handler] of actionHandlers) {
try {
navigator.mediaSession.setActionHandler(action, handler);
} catch (error) {
console.log(`The media session action "${action}" is not supported yet.`);
}
}
إنّ إلغاء ضبط معالِج إجراءات جلسة الوسائط سهل مثل ضبطه على null
.
try {
// Unset the "nexttrack" action handler at the end of a playlist.
navigator.mediaSession.setActionHandler('nexttrack', null);
} catch (error) {
console.log(`The media session action "nexttrack" is not supported yet.`);
}
بعد ضبطها، ستظلّ معالجات إجراءات جلسة الوسائط محفوظة أثناء تشغيل الوسائط. يشبه ذلك نمط مستمعي الأحداث، باستثناء أنّ معالجة حدث تعني أنّ المتصفّح يتوقف عن تنفيذ أي سلوك تلقائي ويستخدم ذلك كإشارة تشير إلى أنّ الموقع الإلكتروني يتيح إجراء الوسائط. وبالتالي، لن يتم عرض عناصر التحكّم في إجراءات الوسائط ما لم يتم ضبط معالِج الإجراءات المناسب.

التشغيل / الإيقاف المؤقت
يشير الإجراء "play"
إلى أنّ المستخدم يريد استئناف تشغيل الوسائط،
بينما يشير الإجراء "pause"
إلى الرغبة في إيقافه مؤقتًا.
يظهر رمز "تشغيل/إيقاف مؤقت" دائمًا في إشعار وسائط، ويعالج المتصفح تلقائيًا أحداث الوسائط ذات الصلة. لإلغاء سلوكه التلقائي، عليك معالجة إجراءات تشغيل الوسائط وإيقافها مؤقتًا كما هو موضّح أدناه.
قد يعتبر المتصفّح أنّ الموقع الإلكتروني لا يشغّل الوسائط عند التقديم أو الترجيع أو carregar، على سبيل المثال. في هذه الحالة، يمكنك إلغاء هذا السلوك من خلال ضبط
navigator.mediaSession.playbackState
على "playing"
أو "paused"
للتأكّد من
بقاء واجهة مستخدِم الموقع الإلكتروني متزامنة مع عناصر التحكّم في إشعارات الوسائط.
const video = document.querySelector('video');
navigator.mediaSession.setActionHandler('play', async () => {
// Resume playback
await video.play();
});
navigator.mediaSession.setActionHandler('pause', () => {
// Pause active playback
video.pause();
});
video.addEventListener('play', () => {
navigator.mediaSession.playbackState = 'playing';
});
video.addEventListener('pause', () => {
navigator.mediaSession.playbackState = 'paused';
});
المقطع الصوتي السابق
يشير الإجراء "previoustrack"
إلى أنّ المستخدم يريد بدء
تشغيل الوسائط الحالية من البداية إذا كان تشغيل الوسائط يتضمن مفهومًا
للبداية، أو الانتقال إلى العنصر السابق في قائمة التشغيل إذا كان تشغيل الوسائط
يتضمن مفهومًا لقائمة التشغيل.
navigator.mediaSession.setActionHandler('previoustrack', () => {
// Play previous track.
});
المقطع الصوتي التالي
يشير الإجراء "nexttrack"
إلى أنّ المستخدم يريد نقل تشغيل الوسائط إلى
العنصر التالي في قائمة التشغيل إذا كان تشغيل الوسائط يتضمّن فكرة قائمة تشغيل.
navigator.mediaSession.setActionHandler('nexttrack', () => {
// Play next track.
});
إيقاف
يشير الإجراء "stop"
إلى أنّ المستخدم يريد إيقاف تشغيل الوسائط
ومحو الحالة إذا كان ذلك مناسبًا.
navigator.mediaSession.setActionHandler('stop', () => {
// Stop playback and clear state if appropriate.
});
ترجيع / تقديم
يشير الإجراء "seekbackward"
إلى أنّ المستخدم يريد إعادة تشغيل الوسائط
لفترة قصيرة، في حين يشير الإجراء "seekforward"
إلى الرغبة في
إعادة تشغيل الوسائط لفترة قصيرة. وفي كلتا الحالتَين، تعني المدة القصيرة بضع ثوانٍ.
قيمة seekOffset
المقدَّمة في معالِج الإجراءات هي الوقت بالثواني الذي يتم خلاله
تحريك وقت تشغيل الوسائط. إذا لم يتم توفيرها (مثل undefined
)، يجب
استخدام وقت معقول (مثلاً من 10 إلى 30 ثانية).
const video = document.querySelector('video');
const defaultSkipTime = 10; /* Time to skip in seconds by default */
navigator.mediaSession.setActionHandler('seekbackward', (details) => {
const skipTime = details.seekOffset || defaultSkipTime;
video.currentTime = Math.max(video.currentTime - skipTime, 0);
// TODO: Update playback state.
});
navigator.mediaSession.setActionHandler('seekforward', (details) => {
const skipTime = details.seekOffset || defaultSkipTime;
video.currentTime = Math.min(video.currentTime + skipTime, video.duration);
// TODO: Update playback state.
});
التقديم أو الإيقاف إلى وقت معيّن
يشير الإجراء "seekto"
إلى أنّ المستخدم يريد نقل وقت تشغيل الوسائط
إلى وقت محدّد.
قيمة seekTime
المقدَّمة في معالِج الإجراءات هي الوقت بالثواني الذي يتم فيه
نقل وقت تشغيل الوسائط.
تكون قيمة القيمة المنطقية fastSeek
المقدَّمة في معالِج الإجراءات صحيحة إذا كان يتم استدعاء الإجراء
مرارًا كجزء من تسلسل ولم يكن هذا هو الطلب الأخير
في هذا التسلسل.
const video = document.querySelector('video');
navigator.mediaSession.setActionHandler('seekto', (details) => {
if (details.fastSeek && 'fastSeek' in video) {
// Only use fast seek if supported.
video.fastSeek(details.seekTime);
return;
}
video.currentTime = details.seekTime;
// TODO: Update playback state.
});
ضبط موضع التشغيل
إنّ عرض موضع تشغيل الوسائط بدقة في الإشعار سهل تمامًا، فما عليك سوى ضبط حالة الموضع في الوقت المناسب كما هو موضّح أدناه. حالة الموضع هي مزيج من معدل تشغيل الوسائط ومدته والوقت الحالي.

يجب تقديم مدة موجبة. يجب أن يكون الموضع موجبًا ويجب أن يكون أقصر من المدة. يجب أن تكون نسبة التشغيل أكبر من 0.
const video = document.querySelector('video');
function updatePositionState() {
if ('setPositionState' in navigator.mediaSession) {
navigator.mediaSession.setPositionState({
duration: video.duration,
playbackRate: video.playbackRate,
position: video.currentTime,
});
}
}
// When video starts playing, update duration.
await video.play();
updatePositionState();
// When user wants to seek backward, update position.
navigator.mediaSession.setActionHandler('seekbackward', (details) => {
/* ... */
updatePositionState();
});
// When user wants to seek forward, update position.
navigator.mediaSession.setActionHandler('seekforward', (details) => {
/* ... */
updatePositionState();
});
// When user wants to seek to a specific time, update position.
navigator.mediaSession.setActionHandler('seekto', (details) => {
/* ... */
updatePositionState();
});
// When video playback rate changes, update position state.
video.addEventListener('ratechange', (event) => {
updatePositionState();
});
يمكنك إعادة ضبط حالة الموضع بسهولة عن طريق ضبطها على null
.
// Reset position state when media is reset.
navigator.mediaSession.setPositionState(null);
إجراءات اجتماعات الفيديو
عندما يضع المستخدم مكالمة الفيديو في نافذة "صورة في صورة"، قد يعرض المتصفّح عناصر تحكّم في الميكروفون والكاميرا وإيقاف المكالمة. عندما ينقر المستخدم على هذه الروابط، يعالجها الموقع الإلكتروني من خلال إجراءات مكالمات الفيديو التالية. للحصول على مثال، اطّلِع على نموذج اجتماع الفيديو.

تبديل الميكروفون
يشير الإجراء "togglemicrophone"
إلى أنّ المستخدم يريد كتم صوت الميكروفون أو إعادته. تُعلم الطريقة setMicrophoneActive(isActive)
المتصفّح
بما إذا كان الموقع الإلكتروني يعتبر الميكروفون مفعّلاً في الوقت الحالي.
let isMicrophoneActive = false;
navigator.mediaSession.setActionHandler('togglemicrophone', () => {
if (isMicrophoneActive) {
// Mute the microphone.
} else {
// Unmute the microphone.
}
isMicrophoneActive = !isMicrophoneActive;
navigator.mediaSession.setMicrophoneActive(isMicrophoneActive);
});
إيقاف الكاميرا أو تشغيلها
يشير الإجراء "togglecamera"
إلى أنّ المستخدم يريد تفعيل
الكاميرا النشطة أو إيقافها. تشير الطريقة setCameraActive(isActive)
إلى ما إذا كان
المتصفّح يعتبر الموقع الإلكتروني نشطًا.
let isCameraActive = false;
navigator.mediaSession.setActionHandler('togglecamera', () => {
if (isCameraActive) {
// Disable the camera.
} else {
// Enable the camera.
}
isCameraActive = !isCameraActive;
navigator.mediaSession.setCameraActive(isCameraActive);
});
قطع الاتصال
يشير الإجراء "hangup"
إلى أنّ المستخدم يريد إنهاء مكالمة.
navigator.mediaSession.setActionHandler('hangup', () => {
// End the call.
});
إجراءات عرض الشرائح
عندما يضع المستخدم عرض الشرائح في نافذة "صورة في صورة"، قد يعرض المتصفّح عناصر تحكّم للتنقّل بين الشرائح. وعندما ينقر المستخدم على هذه الروابط، يعالجها الموقع الإلكتروني من خلال Media Session API. للحصول على مثال، يُرجى الاطّلاع على نموذج عرض العروض التقديمية.
الشريحة السابقة
يشير الإجراء "previousslide"
إلى أنّ المستخدم يريد الرجوع إلى الслайд
السابق عند عرض الشرائح.
navigator.mediaSession.setActionHandler('previousslide', () => {
// Show previous slide.
});
Browser Support
الشريحة التالية
يشير الإجراء "nextslide"
إلى أنّ المستخدم يريد الانتقال إلى الشريحة التالية
أثناء عرض الشرائح.
navigator.mediaSession.setActionHandler('nextslide', () => {
// Show next slide.
});
Browser Support
نماذج
اطّلِع على بعض عيّنات جلسات الوسائط التي تعرض Blender Foundation و أعمال Jan Morgenstern.
الموارد
- مواصفات جلسة الوسائط: wicg.github.io/mediasession
- مشاكل المواصفات: github.com/WICG/mediasession/issues
- أخطاء Chrome: crbug.com